Tidy Tuesday: Coastal Ocean Temperature by Depth

In this tidytuesday, I want to show the process and make a finished polished plot. The data is from the Coastal Monitoring Program, Centre for Marine Applied Research and shows changing temperature at different depths, measured at low-tide.
blogpost
tidytuesday
R
Author

Eloise Newman

Published

April 2026

Show code
# To clean data
library(tidyverse)
library(patchwork) # side by side plots
library(zoo)
library(showtext)
library(ggtext)
# add text for figure
font_add_google("Quantico")
showtext_auto()

tuesdata <- tidytuesdayR::tt_load('2026-03-31')
## OR
tuesdata <- tidytuesdayR::tt_load(2026, week = 13)

ocean_temperature <- tuesdata$ocean_temperature
ocean_temperature_deployments <- tuesdata$ocean_temperature_deployments

First, I want to get a sense of the data; what the columns are, what format the variables are and what kind of story I am interested in.

Show code
ocean_temperature <- ocean_temperature %>% 
  mutate(year = year(ocean_temperature$date),
         month = month(ocean_temperature$date),
         week = week(ocean_temperature$date),
         month = month(ocean_temperature$date)
  )

week_oc_temp <- ocean_temperature %>% 
  rename(depth = sensor_depth_at_low_tide_m) %>%  
  group_by(year, week, depth) %>% 
  summarise(temp_avg_week = mean(mean_temperature_degree_c))
ocean_temperature %>% head()
# A tibble: 6 × 8
  date       sensor_depth_at_low_tide_m mean_temperature_degree_c
  <date>                          <dbl>                     <dbl>
1 2018-02-20                          2                      1.58
2 2018-02-20                          5                      1.50
3 2018-02-20                         10                      1.49
4 2018-02-20                         15                      1.63
5 2018-02-20                         20                      1.84
6 2018-02-20                         30                      1.92
# ℹ 5 more variables: sd_temperature_degree_c <dbl>, n_obs <dbl>, year <dbl>,
#   month <dbl>, week <dbl>
Show code
ggplot(week_oc_temp, aes(y = depth, x = week, colour = temp_avg_week)) +
  geom_point() +
  facet_wrap(~year) +
  theme_minimal()

Change the y-axis scale so more logical for the data, so that the depth of ocean runs from top to bottom.

Show code
ggplot(week_oc_temp, aes(y = depth, x = week, colour = temp_avg_week)) +
  geom_point() +
  scale_y_continuous(trans = "reverse") +
  facet_wrap(~year) +
  theme_minimal()

Legend is annoying me, so changing its orientation and then moving it up to the top

Show code
ggplot(week_oc_temp, aes(y = depth, x = week, colour = temp_avg_week)) +
  geom_point() +
  scale_y_continuous(trans = "reverse") +
  facet_wrap(~year) +
  theme_minimal() +
  guides(colour = guide_colorbar(title.position = "top",
                               barheight = unit(0.4,"cm"),
                               barwidth = unit(7, "cm"),
                               direction = "horizontal"))
ggplot(week_oc_temp, aes(y = depth, x = week, colour = temp_avg_week)) +
  geom_point() +
  scale_y_continuous(trans = "reverse") +
  facet_wrap(~year) +
  theme_minimal() +
  guides(colour = guide_colorbar(title.position = "top",
                               barheight = unit(0.4,"cm"),
                               barwidth = unit(7, "cm"),
                               direction = "horizontal")) +
  theme(legend.position = "top")

Next, Let’s put each year next to each other. The first way I am going to do it is where we use facet_wrap() (alt facet_grid()). I like to specify the precise rows or columns.

Show code
ggplot(week_oc_temp, aes(y = depth, x = week, colour = temp_avg_week)) +
  geom_point() +
  scale_y_continuous(trans = "reverse") +
  facet_wrap(~year, nrow = 1) +
  theme_minimal() +
  guides(colour = guide_colorbar(title.position = "top",
                               barheight = unit(0.4,"cm"),
                               barwidth = unit(7, "cm"),
                               direction = "horizontal")) +
  theme(legend.position = "top")

Great! Those dots are good but they still are hard to interpret. I would like the colours as points but to have a gradient between points in the same week. For an academic paper this may not be appropriate as hiding the real data and data sampling, but for an infographic it can work. There are two options: can use geom_path(), grouping by week, where colour is defined by temperature. Or to use geom_segment().1

1 I also changed the gradient to scale_color_viridis() as the blue was nice but hard to distinguish the range of temperatures.

Show code
# Option 1
    ggplot(week_oc_temp, aes(y = depth, x = week, colour = temp_avg_week, group = week)) +
        geom_path(aes(color = temp_avg_week), linewidth = 1) +
      scale_color_viridis_c() +
      scale_y_reverse()

    # option 2
    ggplot(week_oc_temp, aes(x = week, y = depth)) +
      geom_segment(aes(xend = week,
                       yend = lead(depth),
                       color = temp_avg_week),
                   linewidth = 1) +
      scale_color_viridis_c() +
      scale_y_reverse()
(a) geom_path()
(b) geom_segment()
Figure 1: Gradient of Colours

I like option 1 with geom_path() the best, lets add it to the plot and remove the dots:

Show code
ggplot(week_oc_temp, 
       aes(y = depth, x = week, colour = temp_avg_week)) +
    geom_path(aes(color = temp_avg_week, group = week), linewidth = 1) +
  scale_color_viridis_c() +
  geom_point() +
  scale_y_reverse() + #  scale_y_continuous(trans = "reverse") +
  facet_wrap(~year, nrow = 1) +
  theme_minimal() +
  guides(colour = guide_colorbar(title.position = "top",
                               barheight = unit(0.4,"cm"),
                               barwidth = unit(7, "cm"),
                               direction = "horizontal")) +
  theme(legend.position = "top")
ggplot(week_oc_temp, 
       aes(y = depth, x = week, colour = temp_avg_week)) +
    geom_path(aes(color = temp_avg_week, group = week), linewidth = 1) +
  scale_color_viridis_c() +
  # geom_point() +
  scale_y_reverse() + #  scale_y_continuous(trans = "reverse") +
  facet_wrap(~year, nrow = 1) +
  theme_minimal() +
  guides(colour = guide_colorbar(title.position = "top",
                               barheight = unit(0.4,"cm"),
                               barwidth = unit(7, "cm"),
                               direction = "horizontal")) +
  theme(legend.position = "top")

Looking on the [tidytuesday webpage for the data] (https://github.com/rfordatascience/tidytuesday/blob/main/data/2026/2026-03-31/readme.md) the data comes from Nova Scotia, Canada. I want to add the source, title and labels to the plot. I also want to add in a line for each 10 metres of water depth.

Show code
ggplot(week_oc_temp, 
       aes(y = depth, x = week, colour = temp_avg_week)) +
    geom_path(aes(color = temp_avg_week, group = week), linewidth = 1) +
  scale_color_viridis_c() +
  geom_hline(aes(yintercept = 10), colour = "grey10", linewidth = 0.8) +
  geom_hline(aes(yintercept = 20), colour = "grey10", linewidth = 0.8) +
  geom_hline(aes(yintercept = 30), colour = "grey10", linewidth = 0.8) +
  scale_y_reverse() + #  scale_y_continuous(trans = "reverse") +
  facet_wrap(~year, nrow = 1) +
  labs(
    title = "Changing temperatures in Novia Scotia",
    subtitle = "Over 7 years of aggregated weekly coastal ocean temperatures at 7 depths",
    y = "Depth (m)",
    caption = "Data: Coastal Monitoring Program, Centre for Marine Applied Research, Canada",
    x = "Week"
  ) +
  theme_minimal() +
  guides(colour = guide_colorbar(title.position = "top",
                               barheight = unit(0.4,"cm"),
                               barwidth = unit(7, "cm"),
                               direction = "horizontal")) +
  theme(legend.position = "top",
       # plot.background = element_rect(fill = "#32174F"), 
      #  text = element_text(colour = "white"),
        strip.text = element_text(hjust = 0),
        text = element_text(size = 12),
      plot.caption = element_text(size = rel(0.7))
      )

Nice. I grouped the data by week, but I could also do this daily, which remove the white gaps between the years. The gaps imply separate data, when the data is pretty much continuous.

Show code
ggplot(ocean_temperature, 
       aes(y = sensor_depth_at_low_tide_m, x = date, colour = mean_temperature_degree_c)) +
    geom_path(aes(color = mean_temperature_degree_c, group = date), linewidth = 1) +
  scale_color_viridis_c() +
  geom_hline(aes(yintercept = 10), colour = "grey10", linewidth = 0.8) +
  geom_hline(aes(yintercept = 20), colour = "grey10", linewidth = 0.8) +
  geom_hline(aes(yintercept = 30), colour = "grey10", linewidth = 0.8) +
  scale_y_reverse() + 
  scale_x_date(date_breaks = "year", date_labels = "%Y")+
  #  scale_y_continuous(trans = "reverse") +
  #facet_wrap(~year, nrow = 1) +
  labs(
    title = "Changing temperatures in Novia Scotia",
    subtitle = "Over 7 years of daily coastal ocean temperatures at 7 depths",
    x = "Year",
    y = "Depth (m)",
    caption = "Data: Coastal Monitoring Program, Centre for Marine Applied Research, Canada"
  ) +
  theme_minimal() +
  guides(colour = guide_colorbar(title.position = "top",
                               barheight = unit(0.4,"cm"),
                               barwidth = unit(7, "cm"),
                               direction = "horizontal")) +
  theme(legend.position = "top",
       # plot.background = element_rect(fill = "#32174F"), 
      #  text = element_text(colour = "white"),
        strip.text = element_text(hjust = 0),
        text = element_text(size = 12),
      plot.caption = element_text(size = rel(0.7))
      )

Okay looking good! Now to change the year back to the top of the plot, make the y axis start with zero. I also want to make the legend smaller, with a nice title, and top right of the plot. The fonts could also be changed as well.

Show code
ggplot(ocean_temperature, 
       aes(y = sensor_depth_at_low_tide_m, x = date, colour = mean_temperature_degree_c)) +
  geom_path(aes(color = mean_temperature_degree_c, group = date), linewidth = 1) +
  geom_hline(aes(yintercept = 10), colour = "grey10", linewidth = 0.8) +
  geom_hline(aes(yintercept = 20), colour = "grey10", linewidth = 0.8) +
  geom_hline(aes(yintercept = 30), colour = "grey10", linewidth = 0.8) +
  scale_color_viridis_c(
    name = "Mean Temperature (°C)",
    limits = c(0, 20),
    breaks = seq(0, 20, by = 5),
    labels = function(x) paste0(x, "°C"),
      oob = scales::squish) +
    scale_y_continuous(
      trans = "reverse",
      limits = c(40, 0),
      breaks = seq(0, 40, by = 10),
      expand = c(0, 0))+
  scale_x_date(
      date_breaks = "year", 
      date_labels = "%Y", 
      position = "top") +
  labs(
    title = "Changing temperatures in Novia Scotia",
    subtitle = "This chart shows over 7 years of daily coastal ocean temperatures at 7 different depths.",
    y = "Depth (m)",
    caption = "Visualisation by Eloise Newman • Data by Coastal Monitoring Program, Centre for Marine Applied Research, Canada\nThe index chart shows ocean temperature at varying depths from 2018-2026 • El Niño and La Niña from Jan Null (https://ggweather.com/enso/roni.htm)") +
  theme_minimal() +
  guides(colour = guide_colorbar(title.position = "top",
                               barheight = unit(0.4,"cm"),
                               barwidth = unit(7, "cm"),
                               direction = "horizontal")) +
  theme(
        legend.position = "bottom",
       # plot.background = element_rect(fill = "#32174F"), 
      #  text = element_text(colour = "white"),
        strip.text = element_text(hjust = 0),
        text = element_text(size = 12,family = "Quantico"),
          axis.title = element_text(family = "Quantico"),
      axis.title.x = element_blank(),
      plot.title = element_text(family = "Quantico",face = "bold", size = 20),
      plot.caption = element_text(size = rel(0.5)),
      plot.title.position = "plot",
        plot.subtitle = element_markdown(),
      plot.caption.position = "plot",
      plot.margin = margin(t = 2, r = 0, b = 0, l = 0, unit = "pt")
      )

I want to add El Nino years to the plot to highlight hotter years (in pink!). The data is from Jan Null here.

Show code
ggplot(ocean_temperature, 
       aes(y = sensor_depth_at_low_tide_m, x = date, colour = mean_temperature_degree_c)) +
  geom_path(aes(color = mean_temperature_degree_c, group = date), linewidth = 1) +
  geom_hline(aes(yintercept = 10), colour = "grey10", linewidth = 0.8) +
  geom_hline(aes(yintercept = 20), colour = "grey10", linewidth = 0.8) +
  geom_hline(aes(yintercept = 30), colour = "grey10", linewidth = 0.8) +
  scale_color_viridis_c(
    name = "Mean Temperature (°C)",
    limits = c(0, 20),
    breaks = seq(0, 20, by = 5),
    labels = function(x) paste0(x, "°C"),
      oob = scales::squish) +
    scale_y_continuous(
      trans = "reverse",
      limits = c(40, 0),
      breaks = seq(0, 40, by = 10),
      expand = c(0, 0))+
  scale_x_date(
      date_breaks = "year", 
      date_labels = "%Y", 
      position = "top") +
  annotate(# El Niño 2018–2019
  "segment", x = as.Date("2018-06-01"), xend = as.Date("2019-06-01"),  y = 0, yend = 0,
  linewidth = 2.5,  colour = "#FF69B4" ) +
annotate(# El Niño 2023–2024
  "segment",  x = as.Date("2023-06-01"),  xend = as.Date("2024-06-01"),  y = 0, yend = 0,
  linewidth = 2.5,  colour = "#FF69B4") +
  labs(
    title = "Changing temperatures in Novia Scotia",
    subtitle = "Although a Pacific phenomeon, <b style='color:#FF69B4;'>El Niño</b> can also influence the Atlantic Ocean. This chart<br>shows over 7 years of daily coastal ocean temperatures at 7 different depths.",
    y = "Depth (m)",
    caption = "Visualisation by Eloise Newman • Data by Coastal Monitoring Program, Centre for Marine Applied Research, Canada\nThe index chart shows ocean temperature at varying depths from 2018-2026 • El Niño and La Niña from Jan Null.") +
  theme_minimal() +
  guides(colour = guide_colorbar(title.position = "top",
                               barheight = unit(0.4,"cm"),
                               barwidth = unit(7, "cm"),
                               direction = "horizontal")) +
  theme(
        legend.position = "bottom",
       # plot.background = element_rect(fill = "#32174F"), 
      #  text = element_text(colour = "white"),
        strip.text = element_text(hjust = 0),
        text = element_text(size = 12, family = "Quantico"),
      axis.title = element_text(family = "Quantico"),
      axis.title.x = element_blank(),
      plot.title = element_text(family = "Quantico",face = "bold", size = 20),
      plot.caption = element_text(size = rel(0.5)),
      plot.title.position = "plot",
        plot.subtitle = element_markdown(),
      plot.caption.position = "plot",
      plot.margin = margin(t = 2, r = 0, b = 0, l = 0, unit = "pt")
      )

Show code
#ggsave("changing_Temp_tidytues_2025_04_06.png")
#,  
#       width = 1500, height = 1500, units = "px", dpi = 300 )

This is the final figure (late) on bluesky. To read more about the tidytuesday Data see it here.